package com.mjk.common.tools.encrypt;

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import com.mjk.common.tools.logger.BizLogger;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import cn.hutool.core.codec.Base64;

public class RSAUtils {
	private RSA rsa;

	public RSAUtils() {
		// 生成 RSA 密钥对
		this.rsa = new RSA();
	}

	// 获取公钥
	public String getPublicKey() {
		return rsa.getPublicKeyBase64();
	}

	// 获取私钥
	public String getPrivateKey() {
		return rsa.getPrivateKeyBase64();
	}

	// 使用公钥加密
	public String encryptWithPublicKey(String data) {
		byte[] encryptedData = rsa.encrypt(data.getBytes(), KeyType.PublicKey);
		return Base64.encode(encryptedData);
	}

	// 使用私钥加密
	public String encryptWithPrivateKey(String data) {
		byte[] encryptedData = rsa.encrypt(data.getBytes(), KeyType.PrivateKey);
		return Base64.encode(encryptedData);
	}

	// 使用公钥解密
	public String decryptWithPublicKey(String encryptedData) {
		byte[] decryptedData = rsa.decrypt(Base64.decode(encryptedData), KeyType.PublicKey);
		return new String(decryptedData);
	}

	// 使用私钥解密
	public String decryptWithPrivateKey(String encryptedData) {
		byte[] decryptedData = rsa.decrypt(Base64.decode(encryptedData), KeyType.PrivateKey);
		return new String(decryptedData);
	}

	/**
	 * 签名
	 *
	 * @param date
	 * @return
	 */
	public String sign(String date) {
		Sign sign = SecureUtil.sign(SignAlgorithm.MD5withRSA, getPublicKey(), getPrivateKey());
		return Base64.encode(sign.sign(date));
	}

	/**
	 * 签名验证
	 *
	 * @param data
	 * @param signDate
	 * @return
	 * @throws Exception
	 */
	public boolean verify(byte[] data, String signDate)
			throws Exception {
		Sign sign = SecureUtil.sign(SignAlgorithm.MD5withRSA, getPublicKey(), getPrivateKey());
		return sign.verify(data, signDate.getBytes());
	}
}